home *** CD-ROM | disk | FTP | other *** search
- /* HTMLwriter.c -- HTML output for WWW nodes
- * $Id: SGMLmain.c,v 1.3 93/01/06 18:40:27 connolly Exp Locker: connolly $
- */
-
- /* implements ... */
- #include "HTMLwriter.h"
-
- /* uses ... */
- #include "HTMLdtd.h"
- #include "SGML.h"
-
- #include <string.h>
- #include "object.h"
-
- /* prototypes for private functions... */
-
- static HMWriterProc htmlwriter_new;
- static HMDeleteProc htmlwriter_dt;
-
- static HMStartTagProc start_tag;
- static HMEndTagProc end_tag;
- static HMDataProc data;
-
- HMDoc_Class HTMLwriter = {0, htmlwriter_new, htmlwriter_dt,
- start_tag, end_tag, data,
- html_entity_text};
-
- typedef struct{
- HMStream out;
- HMWriteProc *write;
- enum {start, html, head, body} state;
- }STR;
-
-
- #define STR_puts(s, chars) ((s)->write)((s)->out, (chars), strlen(chars));
-
- static HMDoc*
- htmlwriter_new(out, write)
- HMStream out;
- HMWriteProc* write;
- {
- STR* s = NEW(STR, 1);
- s->out = out;
- s->write = write;
- s->state = start;
-
- return (HMDoc*)s;
- }
-
- static VOID
- htmlwriter_dt(this)
- HMDoc* this;
- {
- FREE(this);
- }
-
-
- static VOID
- data(document, chars, nchars)
- HMDoc* document;
- CONST char* chars;
- int nchars;
- {
- STR* s = (STR*)document;
- char* out;
-
- if(nchars>0){
- int len;
-
- /* fake tag minimization.
- * This is a non-conforming error handling mechanism.
- * But it's expedient.
- */
- switch(s->state){
- case start:
- start_tag(document, "HTML", 0, 0);
- case html:
- start_tag(document, "BODY", 0, 0);
- break;
-
- case head:
- return; /* data in HEAD tag is an error */
-
- }
-
- len = SGML_replen(chars, "<>&");
- out = NEW(char, len + 1);
- SGML_repcpy(out, chars, "<>&");
- (s->write)(s->out, (VOIDPTR)out, (unsigned)len);
- FREE(out);
- }
- }
-
-
- static VOID
- end_tag(document, gi)
- HMDoc* document;
- CONST char* gi;
- {
- STR* s = (STR*)document;
- /*
- * This is a non-conforming error handling mechanism.
- * But it's expedient.@@
- */
- if(!strcmp(gi, "HEAD")
- || !strcmp(gi, "BODY"))
- s->state = html;
- else if (!strcmp(gi, "HTML"))
- s->state = start;
-
- (s->write)(s->out, "\n</", 3);
- STR_puts(s, gi);
- (s->write)(s->out, ">", 1);
- }
-
-
- static int
- start_tag(document, gi, attributes, nattrs)
- HMDoc* document;
- CONST char* gi;
- CONST HMBinding attributes[];
- int nattrs;
- {
- STR* s = (STR*)document;
- int i, len;
- char literal[SGML_LITLEN*6];
- int content = HTML_content(gi);
-
- /* @@ fake tag minimization */
- if(!strcmp(gi, "HTML"))
- s->state = html;
-
- if(!strcmp(gi, "HEAD"))
- s->state = head;
- else if (!strcmp(gi, "BODY"))
- s->state = body;
-
- (s->write)(s->out, "<", 1);
- STR_puts(s, gi);
- for(i = 0; i<nattrs; i++){
- CONST char* name = attributes[i].name;
-
- len = SGML_replen(attributes[i].value, "\"&");
- SGML_repcpy(literal, attributes[i].value, "\"&");
- (s->write)(s->out, " ", 1);
- STR_puts(s, name);
- (s->write)(s->out, "=\"", 2);
- STR_puts(s, literal);
- (s->write)(s->out, "\"", 1);
- }
-
- /* only write out newline for non-empty elements */
- (s->write)(s->out, ">\n", content == SGML_EMPTY ? 1 : 2);
-
- return content;
- }
-
- /*********************
- * Data routines
- *********************/
-
- int
- SGML_replen(data, specials)
- CONST char* data;
- CONST char* specials;
- {
- CONST unsigned char* p = (CONST unsigned char*)data;
- int ret = strlen(data);
-
- while(*p){
- if(strchr(specials, *p))
- ret += (*p>9 ? (*p>99 ? 5 : 4) : 3); /* extra ddd; */
- *p++;
- }
- return ret;
- }
-
-
- char*
- SGML_repcpy(markup, data, specials)
- char* markup;
- CONST char* data;
- CONST char* specials;
- {
- char* dst = markup;
- CONST unsigned char* p = (CONST unsigned char*)data;
- char digit;
-
- while(*p){
- if(strchr(specials, *p)){
- *dst++ = '&'; /* @@ non-ascii compilers! */
- *dst++ = '#';
- if(*p > 99)
- *dst++ = (*p / 100) + '0';
- if(*p > 9)
- *dst++ = ((*p % 100) / 10) + '0';
- *dst++ = (*p % 10) + '0';
- *dst++ = ';';
- p++;
- }else
- *dst++ = *p++;
- }
- *dst = 0;
- return markup;
- }
-